package com.cx.base.day10_wrapperClass;

import com.carrotsearch.sizeof.RamUsageEstimator;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * @Author: robert.song
 * @Date: Created in 2022/5/9
 */
@Slf4j
public class Util_05_BigDecimal {

    public static void main(String[] args) {
//        获取long的最大值:9223372036854775807
        Double d1 = Double.MAX_VALUE;
        log.debug(String.valueOf(d1));
        log.debug("l1数据大小：{}", RamUsageEstimator.sizeOf(d1) + "B");
//        Decimal轻松超过 Double.MAX_VALUE
        BigDecimal bd1 = new BigDecimal("9223372036854775807");
        BigDecimal bd2 = new BigDecimal("92233720368547758070000000");
        log.debug(bd1.toString());
        log.debug(bd2.toString());
        log.debug("bd1数据大小：{}", RamUsageEstimator.sizeOf(bd1) + "B");
        log.debug("bd2数据大小：{}", RamUsageEstimator.sizeOf(bd2) + "B");
//        依旧有精度问题
        BigDecimal bd3 = new BigDecimal(0.05);
        BigDecimal bd4 = new BigDecimal(0.01);
//        结果竟然是0.06000000000000000298372437868010820238851010799407958984375
        log.debug(bd3.add(bd4).toString());
//        若保证精度需用String作为构造参数
        BigDecimal bd5 = new BigDecimal("0.0422424242");
        BigDecimal bd6 = new BigDecimal("0.0934111111");

//        算术运算
//        相加为0.1356，通过setScale设置小数保留数和小数精度
        BigDecimal bd7 = bd5.add(bd6);
        log.debug("bd7: {}", bd7.toString());
        log.debug("bd7: {}", bd7.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        BigDecimal bd8 = bd5.subtract(bd6);
        log.debug("bd8: {}", bd8.setScale(2, BigDecimal.ROUND_CEILING).toString());
        BigDecimal bd9 = bd5.multiply(bd6);
        log.debug("bd9: {}", bd9.setScale(2, BigDecimal.ROUND_CEILING).toString());

        /**
         * divide()：除方法
         * BigDecimal.ROUND_UP：最后一位如果大于0，则向前进一位，正负数都如此；
         * 例如8.1->9； -8.1->-9
         * BigDecimal.ROUND_DOWN：最后一位不管是什么都会被舍弃；
         * 例如8.1->8； -8.1->-8
         * BigDecimal.ROUND_CEILING：如果是正数，按ROUND_UP处理，如果是负数，按照ROUND_DOWN处理；
         * 例如8.1->9； -8.1->-8；所以这种近似的结果都会>=实际值。
         * BigDecimal.ROUND_FLOOR：跟BigDecimal_ROUND_CEILING相反，如果是正数，按ROUND_DOWN处理，如果是负数，按照ROUND_UP处理；
         * 例如8.1->8；-8.1->-9，这种处理的结果<=实际值
         * BigDecimal.ROUND_HALF_UP：如果最后一位<5则舍弃，如果>=5， 向前进一位，即为四舍五入模式；
         * 例如：7.5->8；7.4->7；-7.5->-8
         * BigDecimal.ROUND_HALF_DOWN：如果最后一位<=5则舍弃，如果>5，则向前进一位；
         * 例如：7.5->7；7.6->8；-7.5->-7
         * BigDecimal.ROUND_HALF_EVEN ：如果倒数第二位是奇数，按照BigDecimal.ROUND_HALF_UP处理，如果是偶数，按照BigDecimal.ROUND_HALF_DOWN来处理。
         * 例如：7.5->8；8.5->8；7.4->7；-7.5->-8
         */
        BigDecimal bd10 = bd5.divide(bd6, 3, BigDecimal.ROUND_FLOOR);
        log.debug("bd10: {}", bd10.toString());

        /**
         * 除无法像加减乘那样使用setScale方法，
         * 因为执行divide方法后必须给出确定的长度才能确定返回值内存大小，
         * 所以必须在divide方法中就设置小数数量和小数精度，像上面的方式
         * 而下面的方式则会报算术异常
         */
        BigDecimal bd11 = null;
        try {
            bd11 = bd5.divide(bd6);
            log.debug("bd11: {}", bd11.setScale(3, BigDecimal.ROUND_CEILING).toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

        BigDecimal bd12 = new BigDecimal(12);
        log.debug("bd12：{}", bd12.setScale(4));

    }
}